package com.zhdl.network.service.impl;

import cn.hutool.core.util.HexUtil;
import com.project.command.faq.event.behavior.BehaviorPerform;
import com.project.command.instruction.bo.SingleInstruction;
import com.zhdl.common.util.IdUtil;
import com.zhdl.modules.tools.IntToHexUtil;
import com.zhdl.modules.tools.PublicTools;
import com.zhdl.network.modbus.ModbusRtuRespPkg;
import com.zhdl.network.modbus.after.ModbusAfterService;
import com.zhdl.network.modbus.analysis.ModbusAnalysis;
import com.zhdl.network.modbus.request.WriteSingleKeepRegisterReq;
import com.zhdl.network.service.MotorService;
import com.zhdl.network.service.conf.PortConf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;

import static com.project.command.instruction.strategy.abs.AbsDic.INSTRUCTION_DEFAULT_HEX;

/**
 * 汇川电机指令发送服务 03读寄存器数据 06 16位数据发送 10 32位数据
 */
@Slf4j
@Service
public class MotorServiceImpl implements MotorService {

    @Resource
    private BehaviorPerform behaviorPerform;

    @Resource
    private PortConf portConf;

    /**
     * 设置转速
     */
    @Override
    public void setWheelRatio(String address) {
        //设置要发送的指令字符串
        try {
            WriteSingleKeepRegisterReq writeSingleKeepRegisterReq = new WriteSingleKeepRegisterReq();
            writeSingleKeepRegisterReq.id = address;
            writeSingleKeepRegisterReq.startAddr = "0301";
            writeSingleKeepRegisterReq.writeValue = "0008";
            //获取字节型数据
            byte[] bytes = new ModbusRtuRespPkg().WriteSingleKeepRegister(writeSingleKeepRegisterReq);
            //转换成十进制
            sendCmd(HexUtil.encodeHexStr(bytes));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //INSTRUCTION_DEFAULT_HEX 原始字符串字符串
        //INSTRUCTION_DEFAULT 进行转码后发送执行

    }

    /**
     * 发送指令 - 灵活
     *
     * @param cmd 指令
     */
    @Override
    public void sendCmd(String cmd) {
        SingleInstruction instruction = new SingleInstruction();
        instruction.setInstructionId(IdUtil.getUUID_8());
        instruction.setInstruction(cmd);
        instruction.setBeforeInstructionName(INSTRUCTION_DEFAULT_HEX);
        //默认使用com.zhdl.instruction.strategy包下后置策略
        instruction.setAfterInstructionName(ModbusAfterService.MODBUS_AFTER_SERVICE);
        //客户端通信地址, 串口为数字, 网口为ip+端口       数据来源 : port_comm 或 port_socket 表
        instruction.setPortKey(portConf.getComPortWest());
//        instruction.setPortKey("1");
        //设置协议  数据来源 : protocols 表
        instruction.setProtocols(ModbusAnalysis.MODBUS_ANALYSIS);
        behaviorPerform.perform(instruction);
    }

    /**
     * 电机-设置伺服使能
     */
    @Override
    public void motorWriteReady() {
        String cmd = PublicTools.getString("cmd", "motorRunReady");
        sendCmd(cmd);
        log.info("伺服使能");
    }

    /**
     * 电机-设置电机移动 伺服使能+电机开始多端运动
     * 仅供测试
     */
    @Override
    public void motorWriteRun() {
        String cmd = PublicTools.getString("cmd", "motorRun");
        sendCmd(cmd);
        log.info("电机移动 + cmd + 17");
    }

    /**
     * 电机-设置电机停止运动
     */
    @Override
    public void motorWriteStop() {
        String cmd = PublicTools.getString("cmd", "motorStop");
        sendCmd(cmd);
        log.info("电机停止运动");
    }

    /**
     * 读取电机-当前绝对位置
     */
    @Override
    public void motorReadLocation() {
        String cmd = PublicTools.getString("cmd", "motorLocation");
        sendCmd(cmd);
        log.info("读取电机状态-当前电气位置");
    }

    /**
     * 读取电机-是否回到远点
     */
    @Override
    public void motorReadArriveZero() {
        String cmd = PublicTools.getString("cmd", "motorArriveZero");
        sendCmd(cmd);
        log.info("读取电机状态-当前是否到达远点");
    }

    /**
     * 电机找原点
     */
    @Override
    public void motorWriteZero() {
        String cmd = PublicTools.getString("cmd", "motorWriteZero");
        sendCmd(cmd);
        log.info("电机正在找原点.");
    }

    /**
     * 电机移动距离
     *
     * @param moveDist 移动距离
     */
    @Override
    public void setMoveDist(String address, int moveDist) {
        setSlagMoveDist("01", address, moveDist);
    }

    /**
     * 电机-设置电机功能码06
     */
    @Override
    public void write06(String address, int value) {
        writeSlag06("01", address, value);
    }

    /**
     * 电机当前绝对位置(H0b.07)均与机械原点偏移量(H05.36)
     */
    @Override
    public void readOriginDistance() {
        readSlagOriginDistance("01");
    }

    /**
     * 电机-设置电机回原点
     */
    @Override
    public void motorWriteHome() {
        log.info("电机回原点");
    }

    /**
     * 电机-设置读取电机状态
     * --读取电机是否回到原点
     */
    @Override
    public void motorReadStatus() {
        String cmd = PublicTools.getString("cmd", "motorInfo");
        sendCmd(cmd);
        log.info("读取电机状态");
    }

    /**
     * 除渣电机-设置伺服使能
     */
    @Override
    public void motorWriteSlagReady(String slaveStationId) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr("3100");
        req.setWriteValue("0001");
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister06(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("伺服使能 + cmd + 01");
    }

    /**
     * 除渣电机-设置电机移动 伺服使能+电机开始多端运动
     * 仅供测试
     */
    @Override
    public void motorWriteSlagRun(String slaveStationId) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr("3100");
        req.setWriteValue("0011");
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister06(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("电机移动 + cmd + 17");
    }

    /**
     * 除渣电机-设置电机停止运动
     */
    @Override
    public void motorWriteSlagStop(String slaveStationId) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr("3100");
        req.setWriteValue("0000");
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister06(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("电机停止运动");
    }

    /**
     * 除渣电机找原点
     */
    @Override
    public void motorWriteSlagZero(String slaveStationId) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr("3100");
        req.setWriteValue("0021");
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister06(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("电机正在找原点.");
    }

    /**
     * 读取除渣电机-当前绝对位置
     */
    @Override
    public void motorReadSlagLocation(String slaveStationId, String address) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr(address);
        req.setWriteValue("0002");
        try {
            byte[] bytes = ModbusRtuRespPkg.ReadSingleKeepRegister(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("除渣-读取电机状态");
    }

    /**
     * 除渣电机-电机移动距离
     *
     * @param moveDist 移动距离
     */
    @Override
    public void setSlagMoveDist(String slaveStationId, String address, int moveDist) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr(address);
        req.setWriteValue(IntToHexUtil.HeightLowRollBack(IntToHexUtil.intToHex(moveDist)));
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteMoreKeepRegister(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 除渣电机-设置电机功能码06
     */
    @Override
    public void writeSlag06(String slaveStationId, String address, int value) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr(address);
        req.setWriteValue(IntToHexUtil.HeightLowRollBack(IntToHexUtil.shortToHex(value)));
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister(req);
            sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 除渣电机-电机当前绝对位置(H0b.07)均与机械原点偏移量(H05.36)
     */
    @Override
    public void readSlagOriginDistance(String slaveStationId) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddr("0B07");
        req.setWriteValue("0001");
        try {
            sendCmd(HexUtil.encodeHexStr(ModbusRtuRespPkg.ReadSingleKeepRegister(req)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        req.setStartAddr("0524");
        try {
            sendCmd(HexUtil.encodeHexStr(ModbusRtuRespPkg.ReadSingleKeepRegister(req)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
